

//
//  LcHierarchyManager.m
//  18Birdies
//
//  Created by poleness on 2017/3/13.
//  Copyright © 2017年 Lc. All rights reserved.
//

#import "LcHierarchyManager.h"
#import "BaseViewController.h"

@implementation LcHierarchyManager

+ (UIViewController*)viewControllerOfClass:(Class)aClass
                    inNavigationController:(UINavigationController*)navigationController {
  for (UIViewController* viewController in navigationController.viewControllers) {
    if ([viewController isKindOfClass:aClass]) {
      return viewController;
    }
  }
  return nil;
}

+ (UIViewController*)lastViewControllerOf:(UIViewController*)viewController {
  LC_CHECK_NOT_NULL(viewController);
  NSInteger index =
      [viewController.navigationController.viewControllers indexOfObject:viewController];
  if (index != NSNotFound && index > 0) {
    UIViewController* lastViewController =
        viewController.navigationController.viewControllers[index - 1];
    return lastViewController;
  }
  return nil;
}

+ (BOOL)needDismissPresentedViewController:(UIViewController*)viewController {
  UIViewController* presentedViewController = viewController.presentedViewController;
  if (presentedViewController != nil) {
    if ([presentedViewController isKindOfClass:BaseViewController.class]) {
      BaseViewController* viewController = (BaseViewController*)presentedViewController;
      if (!viewController.dismissed) {
        return YES;
      }
    } else if ([presentedViewController isKindOfClass:UIAlertController.class]) {
      return YES;
    } else if ([presentedViewController isKindOfClass:UINavigationController.class]) {
      NSArray* viewControllers = [(UINavigationController*)presentedViewController viewControllers];
      BaseViewController* viewController = (BaseViewController*)[viewControllers lastObject];
      if (!viewController.dismissed) {
        return YES;
      }
    }
  }
  return NO;
}

+ (void)removeViewController:(UIViewController*)viewController
     inNavigationController:(UINavigationController*)navigationController {
  LC_CHECK_NOT_NULL(viewController);
  LC_CHECK_NOT_NULL(navigationController);
  NSMutableArray* viewControllers = navigationController.viewControllers.mutableCopy;
  if ([viewControllers containsObject:viewController]) {
    [viewControllers removeObject:viewController];
    [navigationController setViewControllers:viewControllers];
  }
}

+ (void)removeViewControllerOfClass:(Class)aClass
             inNavigationController:(UINavigationController*)navigationController {
  if (aClass != nil) {
    [self removeViewControllerOfClasses:@[ aClass ] inNavigationController:navigationController];
  }
}

+ (void)removeViewControllerOfClasses:(NSArray*)aClasses
               inNavigationController:(UINavigationController*)navigationController {
  LC_CHECK_NOT_NULL(navigationController);
  NSMutableArray* viewControllers = navigationController.viewControllers.mutableCopy;
  NSMutableArray* needRemoved = [NSMutableArray arrayWithCapacity:viewControllers.count];
  for (int i = 0; i < viewControllers.count; ++i) {
    UIViewController* viewController = viewControllers[i];
    if ([aClasses containsObject:viewController.class]) {
      [needRemoved addObject:viewControllers];
    }
  }
  if (needRemoved.count > 0) {
    [viewControllers removeObjectsInArray:needRemoved];
    [navigationController setViewControllers:viewControllers];
  }
}


#pragma mark - View Hierachy

+ (UINavigationController*)navigationControllerOfViewController:(UIViewController*)viewController {
  UINavigationController* rootNavigationController = nil;
  if (viewController != nil) {
    if (viewController.presentingViewController != nil &&
        viewController.navigationController.viewControllers.count <= 1) {
      UIViewController* rootSelectedTaBarController =
          [self rootSelectedTaBarController:viewController.presentingViewController];
      if (rootSelectedTaBarController != nil) {
        return [self navigationControllerOfViewController:rootSelectedTaBarController];
      } else {
        rootNavigationController =
            [self navigationController:viewController.presentingViewController];
      }
    } else {
      rootNavigationController = [self navigationController:viewController];
    }
  }
  return rootNavigationController;
}

+ (UIViewController*)rootSelectedTaBarController:(UIViewController*)viewController {
  if ([viewController isKindOfClass:UITabBarController.class]) {
    return [(UITabBarController*)viewController selectedViewController];
  } else if ([viewController isKindOfClass:UINavigationController.class]) {
    UIViewController* subViewController =
        [(UINavigationController*)viewController viewControllers][0];
    if ([subViewController isKindOfClass:UITabBarController.class]) {
      return [(UITabBarController*)subViewController selectedViewController];
    }
  }
  return nil;
}

+ (UINavigationController*)navigationController:(UIViewController*)viewController {
  UINavigationController* navigationController = nil;
  if ([viewController isKindOfClass:UINavigationController.class]) {
    navigationController = (UINavigationController*)viewController;
  } else {
    navigationController = viewController.navigationController;
  }
  return navigationController;
}

+ (NSString*)currentCompleteHierarchyContext {
  UIViewController* currentViewController = [UIViewController currentViewController];
  NSString* context = nil;
  if (currentViewController != nil) {
    BOOL moreThanOneView = NO;
    context = currentViewController.hierarchyContext;
    UINavigationController* rootNavigationController =
        [self navigationControllerOfViewController:currentViewController];
    NSInteger count = rootNavigationController.viewControllers.count;
    for (NSInteger i = count - 1; i >= 0; --i) {
      UIViewController* viewController = rootNavigationController.viewControllers[i];
      if (![currentViewController isEqual:viewController]) {
        moreThanOneView = YES;
        context = [NSString stringWithFormat:@"%@-%@", viewController.hierarchyContext, context];
      }
    }
    if (moreThanOneView) {
      context = [context stringByAppendingString:@"[current]"];
    }
  }
  return context;
}

+ (NSString*)currentBriefHierarchyContext {
  __block UIViewController* currentViewController = nil;
  if ([NSThread isMainThread]) {
    currentViewController = [UIViewController currentViewController];
  } else {
    dispatch_sync(dispatch_get_main_queue(), ^{
      currentViewController = [UIViewController currentViewController];
    });
  }
  NSString* context = nil;
  if (currentViewController != nil) {
    BOOL moreThanOneView = NO;
    context = currentViewController.hierarchyContext;
    NSArray* viewControllers =
        [self navigationControllerOfViewController:currentViewController].viewControllers;
    NSInteger count = viewControllers.count;
    for (NSInteger i = count - 1; (i > count - 4) && (i >= 0); --i) {
      UIViewController* viewController = viewControllers[i];
      if (![currentViewController isEqual:viewController]) {
        moreThanOneView = YES;
        context = [NSString stringWithFormat:@"%@-%@", viewController.hierarchyContext, context];
      }
    }
    if (moreThanOneView) {
      context = [context stringByAppendingString:@"[current]"];
    }
  }
  return context;
}

@end
